package com.clever.auth.shiro;

import com.clever.auth.dto.MemberDto;
import com.clever.auth.dto.RoleDto;
import com.clever.auth.mapper.MemberRoleRelationMapper;
import com.clever.auth.service.MemberService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * @author ChenWang
 * @date 2020/12/14 08:48
 * @since JDK 1.8
 */
public class LoginRealms extends AuthorizingRealm {
    @Resource
    MemberService memberService;
    @Resource
    MemberRoleRelationMapper memberRoleRelationMapper;
    /**
     * 授权
     *
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 获取当前登录的用户信息 --> 用户id
        MemberDto memberDto = (MemberDto) principals.getPrimaryPrincipal();
        // 从数据库获取 权限数据
        List<RoleDto> roleDtos = memberRoleRelationMapper.selectByMemberId(memberDto.getMid());
        Set<String> roles = new HashSet<>();
        Set<String> permissions = new HashSet<>();
        roleDtos.forEach(role->{
            roles.add(role.getRoleName());
            role.getPermissions().forEach(permission-> permissions.add(permission.getPerName()));
        });
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setRoles(roles);
        info.setStringPermissions(permissions);
        return info;
    }

    /**
     * 认证
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        /**
         * 第一步 authenticationToken获取
         */
        String username = (String) token.getPrincipal();
        /**
         * 第二步 数据库取数据
         */
        MemberDto memberDto = memberService.findByUsername(username);
        /**
         * 第三步 业务逻辑判断
         */
        if (Objects.isNull(memberDto)) {
            throw new UnknownAccountException("账号不存在");
        }
        if (!memberDto.getLocked()) {
            throw new LockedAccountException("账号被锁定");
        }
        /**
         * 第四步 创建AuthenticationInfo对象
         * 参数:
         * 1. Object principal 从数据库中查询的user对象   也可以是用户名(不推荐)
         *
         * 2. Object hashedCredentials, 从数据库中获取的用户的密码
         *
         * 3. hashedCredentials ByteSource credentialsSalt 加密盐
         *
         * 4. userName  从token中获取的用户名
         */
        return new SimpleAuthenticationInfo(memberDto,memberDto.getPassword(),null,username);
    }
}
